# -*- coding: utf-8 -*-  # 添加此行

import base64
import logging
from fastapi import FastAPI, File, HTTPException, Request, UploadFile, WebSocket
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
from core.Router import ALLRouter
from contextlib import asynccontextmanager
from database.database import Base, engine
from init_db import create_database_if_not_exists

from pathlib import Path
import shutil
import os
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse, JSONResponse
from fastapi.staticfiles import StaticFiles

from pydantic import BaseModel
from pathlib import Path
import os

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from routers import user, user_stats
from database.database import engine
from models import user as user_model, user_stats as user_stats_model
from models import ota as ota_model

# 创建数据库表
user_model.Base.metadata.create_all(bind=engine)
user_stats_model.Base.metadata.create_all(bind=engine)
ota_model.Base.metadata.create_all(bind=engine)

app = FastAPI(title="FastAPI Project", version="1.0.0")

# 配置CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 包含路由
app.include_router(user.router, prefix="/api/users", tags=["users"])
app.include_router(user_stats.router, prefix="/api/stats", tags=["user_stats"])

@app.get("/")
def read_root():
    return {"message": "Welcome to FastAPI Project!"}

@app.get("/health")
def health_check():
    return {"status": "healthy"}


# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(),
        logging.FileHandler('app.log', encoding='utf-8')
    ]
)
logger = logging.getLogger(__name__)

# --------------------------------------------------------
# Pydantic 模型：客户端通过 JSON 传来 filename 和 content_base64
# --------------------------------------------------------
class UploadBase64Schema(BaseModel):
    filename: str          # 保存到服务器的文件名，例如 "xxx.wav"
    content_base64: str    # 完整的 Base64 字符串，不要加 "data:..." 前缀，只需要纯的 Base64




@asynccontextmanager
async def lifespan(app: FastAPI):
    # ⏳ 应用启动时执行
    create_database_if_not_exists()
    Base.metadata.create_all(bind=engine)
    print("✅ 数据库初始化完成")
    yield
    # 🧹 应用关闭时执行（可选）
    print("👋 应用关闭")

# 启动时创建表（实际项目可改为 Alembic 管理迁移）
# @app.on_event("startup")
# def startup():
#     print("🔌 正在连接数据库并创建表...")
#     create_database_if_not_exists()
#     Base.metadata.create_all(bind=engine)


# 创建 FastAPI 实例
# app = FastAPI(lifespan=lifespan)

# 1. 如果你想将上传后的文件放在本地某个目录，例如 ./uploaded_files/
UPLOAD_DIR = Path("./uploaded_files")
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)

# 先注册API路由，避免与静态文件冲突
app.include_router(ALLRouter)

# 2.（可选）将上传目录挂载为静态文件，以便后续直接通过 URL 访问
#    比如上传后保存为 uploaded_files/abcd.png，可以通过 http://localhost:8000/static/abcd.png 访问
app.mount("/static", StaticFiles(directory=str(UPLOAD_DIR)), name="static")
# 将本地目录 uploaded_files 挂载到 /files 路径，让客户端可以通过 /files/<filename> 访问
app.mount("/files", StaticFiles(directory=str(UPLOAD_DIR)), name="files")

# 挂载static目录，用于访问HTML测试页面
app.mount("/static-pages", StaticFiles(directory="static"), name="static-pages")

app.mount("/music/tts", StaticFiles(directory=os.path.abspath("music/tts")), name="tts")

# 添加调试信息
print("=== 路由注册信息 ===")
print(f"总路由数量: {len(app.routes)}")
ota_routes = [r for r in app.routes if '/ota' in r.path]
print(f"OTA路由数量: {len(ota_routes)}")
for route in ota_routes:
    print(f"  - {route.path}")


# # 添加 HTML 页面访问路由
# @app.get("/test/speech", summary="语音识别测试界面")
# async def get_speech_test_page():
#     return FileResponse("static/speech_test.html", media_type="text/html")



# 配置 CORS，允许所有来源进行连接
# app.add_middleware(
#     CORSMiddleware,
#     allow_origins=["*"],  # 允许所有来源
#         # 或者只允许特定域名
#     # allow_origins=["http://www.websocket-test.com"],  
#     allow_credentials=True,
#     allow_methods=["*"],  # 允许所有 HTTP 方法
#     allow_headers=["*"],  # 允许所有头部
# )

# 根路由
# @app.get("/")
# async def root():
#     return {"message": "Hello World"}






@app.post("/upload")
async def upload_base64(request: Request, payload: UploadBase64Schema):
    """
    接收类似下面格式的 JSON：
    {
      "filename": "xxx.wav",
      "content_base64": "<Base64 字符串>"
    }
    后端将 Base64 解码后写入本地 UPLOAD_DIR，并返回：
    {
      "code": 0,
      "message": "success",
      "data": {
        "url": "http://127.0.0.1:7777/files/xxx.wav",
        "size": 14940,
        "type": "wav"
      }
    }
    """
    # 1. 准备保存路径
    filename = payload.filename.strip()
    if not filename:
        raise HTTPException(status_code=400, detail="filename 不能为空")
    destination: Path = UPLOAD_DIR / filename

    # 2. 解码 Base64 字符串（如果含有前缀 "data:xxx;base64,"，需先去掉这一段，仅留纯 Base64 部分
    b64_str = payload.content_base64
    if "," in b64_str and b64_str.startswith("data:"):
        # 如果前端误把 data URL 也传过来了，比如 "data:audio/wav;base64,AAAA..."
        # 只要逗号之后的部分才是真正的 base64
        b64_str = b64_str.split(",", 1)[1]

    try:
        file_bytes = base64.b64decode(b64_str)
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Base64 解码失败：{e}")

    # 3. 把 file_bytes 写入磁盘
    try:
        with destination.open("wb") as f:
            f.write(file_bytes)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"保存文件失败：{e}")

    # 4. 计算文件大小
    file_size = destination.stat().st_size  # 单位：字节

    # 5. 提取后缀名作为 type（不包含前导点）
    suffix = destination.suffix.lower()            # e.g. ".wav"
    file_type = suffix[1:] if suffix.startswith(".") else suffix  # e.g. "wav"

    # 6. 拼接可访问的 URL（用 request.base_url 取到域名+端口）
    base_url = str(request.base_url)                # e.g. "http://127.0.0.1:7777/"
    file_url = f"{base_url}files/{filename}"        # e.g. "http://127.0.0.1:7777/files/xxx.wav"

    # 7. 按照约定格式返回
    return JSONResponse({
        "code": 0,
        "message": "success",
        "data": {
            "url": file_url,
            "size": file_size,
            "type": file_type
        }
    })






# @app.post("/upload")
# async def upload_file(request: Request, file: UploadFile = File(...)):
#     """
#     接收单个文件上传，并按指定格式返回：
#     {
#       "code": 0,
#       "message": "success",
#       "data": {
#         "url": "...",
#         "size": ...,
#         "type": "..."
#       }
#     }
#     """
#     # 可选：校验 Content-Type，比如只允许 wav 格式
#     # if file.content_type != "audio/wav":
#     #     raise HTTPException(status_code=400, detail="只允许上传 WAV 文件")

#     # 构造本地保存路径
#     destination: Path = UPLOAD_DIR / file.filename

#     # 保存文件到本地
#     try:
#         with destination.open("wb") as buffer:
#             shutil.copyfileobj(file.file, buffer)
#     except Exception as e:
#         # 保存失败，返回 500
#         raise HTTPException(status_code=500, detail=f"保存文件失败：{e}")
#     finally:
#         await file.close()

#     # 获取文件大小（字节数）
#     file_size = destination.stat().st_size  # e.g. 14940

#     # 提取文件后缀（不包含前导点），若上传文件名为 xxx.wav，则 file_type = "wav"
#     suffix = destination.suffix.lower()
#     file_type = suffix[1:] if suffix.startswith('.') else suffix  # 去掉前面的 "."

#     # 构造文件访问 URL：例如 http://your-server.com/files/xxx.wav
#     #
#     # 这里的 request.url_for("files", path=file.filename) 只能生成内部 StaticFiles 路径，
#     # 例如 "/files/xxx.wav"。如果需要包含域名，可使用：
#     # request.base_url 对象拼接，例如 "http://127.0.0.1:8000/"
#     #
#     # 完整示例：若部署后域名为 your-server.com，可把 host:port 换成自己域名。
#     #
#     # 下面演示一种通用方式：先拿到当前请求的 base_url（含 http://host:port/），
#     # 再拼接静态访问路径。
#     base_url = str(request.base_url)  # 例如 "http://127.0.0.1:8000/"
#     file_url = f"{base_url}files/{file.filename}"  # e.g. "http://127.0.0.1:8000/files/xxx.wav"

#     # 最后按指定格式返回
#     return JSONResponse({
#         "code": 0,
#         "message": "success",
#         "data": {
#             "url": file_url,
#             "size": file_size,
#             "type": file_type
#         }
#     })

# @app.websocket("/ws")
# async def websocket_endpoint(websocket: WebSocket):
#     try:
#         await websocket.accept()
#         print("WebSocket 握手成功，连接已建立")
#         while True:
#             data = await websocket.receive_text()
#             print(f"收到消息: {data}")
#             await websocket.send_text(f"收到消息: {data}")
#     except Exception as e:
#         print(f"WebSocket 错误: {e}")
# # WebSocket 路由
# @app.websocket("/ws")
# async def websocket_endpoint(websocket: WebSocket):
#     await websocket.accept()  # 接受连接
#     while True:
#         data = await websocket.receive_text()  # 接收消息
#         print(f"Received data: {data}")
#         await websocket.send_text(f"Message text was: {data}")  # 发送回客户端

# @app.websocket("/ws")
# async def websocket_endpoint(websocket: WebSocket):
#     # 检查 Token 或其他凭据
#     token = websocket.query_params.get("token")
#     if not token or not validacte_token(token):  # 假设 validate_token 是验证逻辑
#         await websocket.close(code=403)  # 拒绝连接
#         return

#     await websocket.accept()
#     try:
#         while True:
#             data = await websocket.receive_text()
#             await websocket.send_text(f"收到消息: {data}")
#     except WebSocketDisconnect:
#         print("客户端断开连接")


# 启动服务器
if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=8000)
    
    # uvicorn.run(app, host='127.0.0.1', port=8000)
